package com.gs.pdf.to.word.swing;


import com.gs.pdf.to.word.pdf.AdvancedPDFExtractor;
import com.gs.pdf.to.word.pdf.StyledDOCXWriter;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;

public class PDFToWordGUI extends JFrame {
    private JTextField pdfPathField;
    private JTextField outputDirField;
    private JTextArea logArea;
    private JProgressBar progressBar;
    private JButton convertButton, selectPdfButton, selectDirButton;

    public PDFToWordGUI() {
        super("PDF转Word工具");
        initializeUI();
    }

    private void initializeUI() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(650, 450);
        setLayout(new BorderLayout(10, 10));
        setPreferredSize(new Dimension(650, 450));
        setLocationRelativeTo(null);

        // === 顶部输入区 ===
        JPanel inputPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(8, 10, 8, 10);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        // 行1：PDF 文件
        gbc.gridx = 0;
        gbc.gridy = 0;
        inputPanel.add(new JLabel("PDF文件路径:"), gbc);

        pdfPathField = new JTextField(30);
        gbc.gridx = 1;
        inputPanel.add(pdfPathField, gbc);

        selectPdfButton = new JButton("选择...");
        gbc.gridx = 2;
        inputPanel.add(selectPdfButton, gbc);

        // 行2：输出目录
        gbc.gridx = 0;
        gbc.gridy = 1;
        inputPanel.add(new JLabel("输出目录:"), gbc);

        outputDirField = new JTextField(30);
        gbc.gridx = 1;
        inputPanel.add(outputDirField, gbc);

        selectDirButton = new JButton("浏览...");
        gbc.gridx = 2;
        inputPanel.add(selectDirButton, gbc);

        add(inputPanel, BorderLayout.NORTH);

        // === 中部：日志输出 ===
        logArea = new JTextArea();
        logArea.setEditable(false);
        logArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
        logArea.setMargin(new Insets(10, 10, 10, 10));

        JScrollPane scrollPane = new JScrollPane(logArea);
        scrollPane.setBorder(BorderFactory.createTitledBorder("处理日志"));

        add(scrollPane, BorderLayout.CENTER);

        // === 底部：进度条 + 按钮 ===
        JPanel bottomPanel = new JPanel(new BorderLayout(10, 10));
        bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true);
        progressBar.setValue(0);
        bottomPanel.add(progressBar, BorderLayout.CENTER);

        convertButton = new JButton("开始转换");
        convertButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
        bottomPanel.add(convertButton, BorderLayout.EAST);

        add(bottomPanel, BorderLayout.SOUTH);

        // === 默认值 ===
        outputDirField.setText(System.getProperty("user.home") + "/Desktop");

        // === 事件绑定 ===
        selectPdfButton.addActionListener(e -> selectPdfFile());
        selectDirButton.addActionListener(e -> selectOutputDirectory());
        convertButton.addActionListener(e -> startConversion());
    }

    private void selectPdfFile() {
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("选择PDF文件");
        fc.setFileFilter(new FileNameExtensionFilter("PDF 文件 (*.pdf)", "pdf"));
        if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            pdfPathField.setText(fc.getSelectedFile().getAbsolutePath());
        }
    }

    private void selectOutputDirectory() {
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("选择输出目录");
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            outputDirField.setText(fc.getSelectedFile().getAbsolutePath());
        }
    }

    private void startConversion() {
        String pdfPath = pdfPathField.getText().trim();
        String outputDir = outputDirField.getText().trim();

        // 校验输入
        if (pdfPath.isEmpty()) {
            showError("请输入或选择PDF文件路径。");
            return;
        }
        if (outputDir.isEmpty()) {
            showError("请输入或选择输出目录。");
            return;
        }

        File pdfFile = new File(pdfPath);
        if (!pdfFile.exists()) {
            showError("PDF文件不存在，请检查路径。");
            return;
        }
        if (!pdfFile.getName().toLowerCase().endsWith(".pdf")) {
            showError("请选择一个有效的PDF文件。");
            return;
        }

        File dir = new File(outputDir);
        if (!dir.exists() && !dir.mkdirs()) {
            showError("无法创建输出目录：" + outputDir);
            return;
        }
        if (!dir.isDirectory()) {
            showError("输出路径必须是一个目录。");
            return;
        }

        // 输出文件路径
        String baseName = Pattern.compile("\\.pdf$", Pattern.CASE_INSENSITIVE)
                .matcher(pdfFile.getName())
                .replaceAll("");
        String outputPath = new File(dir, baseName + ".docx").getAbsolutePath();

        // 清空日志，重置进度
        logArea.setText("");
        progressBar.setValue(0);
        convertButton.setEnabled(false);

        // 启动后台任务
        SwingWorker<Void, String> worker = new SwingWorker() {
            @Override
            protected Void doInBackground() throws Exception {
                publish("✅ 开始处理: " + pdfFile.getName());

                try (PDDocument doc = PDDocument.load(pdfFile)) {
                    int totalPages = doc.getNumberOfPages();
                    publish("📊 共 " + totalPages + " 页");

                    AdvancedPDFExtractor extractor = null;

                    for (int i = 0; i < totalPages; i++) {
                        PDPage page = doc.getPage(i);
                        publish("📄 正在处理第 " + (i + 1) + "/" + totalPages + " 页...");

                        extractor = new AdvancedPDFExtractor(page);
                        extractor.processPage(page);

                        int progress = (int) (((double) (i + 1) / totalPages) * 100);
                        setProgress(progress);
                    }

                    if (extractor != null && !extractor.getContent().isEmpty()) {
                        StyledDOCXWriter.write(extractor.getContent(), outputPath);
                        publish("🎉 转换成功！文件已保存至：\n   " + outputPath);
                    } else {
                        publish("⚠️  警告：未提取到有效内容。");
                    }
                } catch (IOException e) {
                    publish("❌ 文件读写错误: " + e.getMessage());
                    throw e;
                } catch (Exception e) {
                    publish("❌ 未知错误: " + e.getMessage());
                    throw e;
                }

                return null;
            }

            /**
             * Receives data chunks from the {@code publish} method asynchronously on the
             * <i>Event Dispatch Thread</i>.
             *
             * <p>
             * Please refer to the {@link #publish} method for more details.
             *
             * @param chunks intermediate results to process
             * @see #publish
             */
            @Override
            protected void process(List chunks) {
                for (Object line : chunks) {
                    logArea.append(line + "\n");
                }
                logArea.setCaretPosition(logArea.getDocument().getLength());
            }

            @Override
            protected void done() {
                try {
                    get(); // 等待完成
                    progressBar.setValue(100);
                    JOptionPane.showMessageDialog(PDFToWordGUI.this, "转换已完成！", "成功", JOptionPane.INFORMATION_MESSAGE);
                } catch (InterruptedException | ExecutionException e) {
                    String msg = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
                    logArea.append("❌ 转换失败: " + msg + "\n");
                    JOptionPane.showMessageDialog(PDFToWordGUI.this, "转换失败: " + msg, "错误", JOptionPane.ERROR_MESSAGE);
                } finally {
                    convertButton.setEnabled(true);
                }
            }
        };

        worker.execute();
    }

    private void showError(String message) {
        JOptionPane.showMessageDialog(this, message, "输入错误", JOptionPane.WARNING_MESSAGE);
    }
}